package cn.schoolwow.quickserver.handler;

import cn.schoolwow.quickserver.domain.Client;
import cn.schoolwow.quickserver.interceptor.HandlerInterceptor;
import cn.schoolwow.quickserver.interceptor.Interceptor;
import cn.schoolwow.quickserver.util.AntPatternMatcher;
import cn.schoolwow.quickserver.util.ExceptionHandlerUtil;

import java.util.Collection;

/**
 * 请求分发
 */
public class DispatcherHandler implements Handler {
    @Override
    public Handler handle(Client client) throws Exception {
        //获取过滤器列表
        Collection<HandlerInterceptor> interceptorList = client.serverConfigMeta.applicationContext.getBeansOfType(HandlerInterceptor.class).values();

        for (HandlerInterceptor handlerInterceptor : interceptorList) {
            if (matchInterceptor(client.httpRequestMeta.uri.getPath(), handlerInterceptor)) {
                handlerInterceptor.preHandle(client.httpRequest, client.httpResponse, client.httpSession);
            }
        }

        Handler handler = new ControllerHandler();
        while (!(handler instanceof HttpResponseHandler)) {
            try {
                handler = handler.handle(client);
            }catch (Exception e){
                ExceptionHandlerUtil.handleExceptionHandler(client,e);
                handler = new HttpResponseHandler();
            }
        }

        for (HandlerInterceptor handlerInterceptor : interceptorList) {
            if (matchInterceptor(client.httpRequestMeta.uri.getPath(), handlerInterceptor)) {
                handlerInterceptor.postHandle(client.httpRequest, client.httpResponse, client.httpSession);
            }
        }

        for (HandlerInterceptor handlerInterceptor : interceptorList) {
            if (matchInterceptor(client.httpRequestMeta.uri.getPath(), handlerInterceptor)) {
                handlerInterceptor.beforeResponse(client.httpRequest, client.httpResponse, client.httpSession);
            }
        }
        return handler;
    }

    /**
     * 路径是否匹配拦截器
     */
    private boolean matchInterceptor(String uri, HandlerInterceptor handlerInterceptor) {
        Interceptor interceptor = handlerInterceptor.getClass().getDeclaredAnnotation(Interceptor.class);
        if (null == interceptor) {
            return false;
        }
        for (String excludePattern : interceptor.excludePatterns()) {
            if (AntPatternMatcher.match(uri, excludePattern)) {
                return false;
            }
        }
        for (String pattern : interceptor.patterns()) {
            if (AntPatternMatcher.match(uri, pattern)) {
                return true;
            }
        }
        return false;
    }
}